home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / sat / msat09.tgz / UPLOAD.C < prev    next >
Text File  |  1994-09-17  |  12KB  |  555 lines

  1. /*
  2.  *   Copyright 1992, 1993, 1994 John Melton (G0ORX/N6LYT)
  3.  *              All Rights Reserved
  4.  *
  5.  *   This program is free software; you can redistribute it and/or modify
  6.  *   it under the terms of the GNU General Public License as published by
  7.  *   the Free Software Foundation; either version 1, or (at your option)
  8.  *   any later version.
  9.  *
  10.  *   This program is distributed in the hope that it will be useful,
  11.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *   GNU General Public License for more details.
  14.  *
  15.  *   You should have received a copy of the GNU General Public License
  16.  *   along with this program; if not, write to the Free Software
  17.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20.  
  21. /*
  22.     upload.c
  23.  
  24.     Pacsat Upload for Linux and X-Windows
  25.  
  26.     This program has been run using the 1.0 version of the
  27.     Linux kernel with the patches from Alan Cox to provide AX.25
  28.     encapsulation in the SLIP protocol(verion 0.12).
  29.  
  30.     The TNC must be setup for KISS protocol.
  31.  
  32.     John Melton
  33.     G0ORX, N6LYT
  34.  
  35.     4 Charlwoods Close
  36.     Copthorne
  37.     West Sussex
  38.     RH10 3QZ
  39.     England
  40.  
  41.     INTERNET:    g0orx@amsat.org
  42.             n6lyt@amsat.org
  43.             john@images.demon.co.uk
  44.             J.D.Melton@slh0613.icl.wins.co.uk
  45.  
  46.     History:
  47.  
  48.     0.1    cloned from (x)upload.c        G4KLX
  49.     0.2    handle short writes        G4KLX
  50. */
  51.  
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <unistd.h>
  56. #include <sys/time.h>
  57. #include <sys/types.h>
  58. #include <sys/wait.h>
  59. #include <fcntl.h>
  60. #include <dirent.h>
  61. #include <sys/socket.h>
  62. #include <linux/ax25.h>
  63. #include <signal.h>
  64. #include <ctype.h>
  65.  
  66. #include <X11/Intrinsic.h>
  67.  
  68. #include "header.h"
  69. #include "ftl0.h"
  70.  
  71. extern char satellite[];
  72. extern char myCall[];
  73.  
  74. #define IDLE            0
  75. #define LOGGING_IN        1
  76. #define REQUESTING_UPLOAD    2
  77. #define UPLOADING        3
  78. #define SENT_END_DATA        4
  79.  
  80. int state = IDLE;
  81.  
  82. int fd[];
  83. int s;
  84. FILE *fp;
  85. unsigned long fileId;
  86. long offset;
  87. int fileLength;
  88. UPLOAD_REQUEST *ul_request;
  89. UPLOAD_RESPONSE *ul_response;
  90. unsigned long uploadFileId;
  91. unsigned char buffer[1024];
  92. extern int maxFrame;
  93. extern int T1;
  94.     
  95. #define MAXHEADER 1024
  96. unsigned char header[MAXHEADER];
  97. int nHeader;
  98.  
  99. char msg[256];
  100.  
  101. int convert_call(char *, struct full_sockaddr_ax25 *);
  102.  
  103. int writen(int fd, char *ptr, int n)
  104. {
  105.     int nleft, nwritten;
  106.  
  107.     nleft = n;
  108.  
  109.     while (nleft > 0)
  110.     {
  111.         if ((nwritten = write(fd, ptr, nleft)) <= 0)
  112.             return nwritten;
  113.  
  114.         nleft -= nwritten;
  115.         ptr   += nwritten;
  116.     }
  117.  
  118.     return n;
  119. }
  120.  
  121. void update_status(char *msg)
  122. {
  123.     writen(fd[1], msg, strlen(msg) + 1);
  124. }
  125.  
  126. void error(char *msg)
  127. {
  128.     update_status(msg);
  129.  
  130.     close(s);
  131.     fclose(fp);
  132.  
  133.     sleep(1);
  134.     exit(1);
  135. }
  136.  
  137. void ftl0_error(char *msg, int err_code)
  138. {
  139.     char text[128];
  140.  
  141.     switch (err_code)
  142.     {
  143.         case ER_ILL_FORMED_CMD:
  144.             sprintf(text, "%s: ILL_FORMED_CMD", msg);
  145.             break;
  146.         case ER_BAD_CONTINUE:
  147.             sprintf(text, "%s: BAD_CONTINUE", msg);
  148.             break;
  149.         case ER_SERVER_FSYS:
  150.             sprintf(text, "%s: SERVER_FSYS", msg);
  151.             break;
  152.         case ER_NO_SUCH_FILE_NUMBER:
  153.             sprintf(text, "%s: NO_SUCH_FILE_NUMBER", msg);
  154.             break;
  155.         case ER_FILE_COMPLETE:
  156.             sprintf(text, "%s: FILE_COMPLETE", msg);
  157.             break;
  158.         case ER_NO_ROOM:
  159.             sprintf(text, "%s: NO_ROOM", msg);
  160.             break;
  161.         case ER_BAD_HEADER:
  162.             sprintf(text, "%s: BAD_HEADER", msg);
  163.             break;
  164.         case ER_HEADER_CHECK:
  165.             sprintf(text, "%s: HEADER_CHECK", msg);
  166.             break;
  167.         case ER_BODY_CHECK:
  168.             sprintf(text, "%s: BODY_CHECK", msg);
  169.             break;
  170.         default:
  171.             sprintf(text, "%s: ftl0 error %d", msg, err_code);
  172.             break;
  173.     }
  174.  
  175.     error(text);
  176. }
  177.  
  178. void socket_error(char *msg, int err_code)
  179. {
  180.     char text[128];
  181.  
  182.     switch (err_code)
  183.     {
  184.         case ECONNRESET:
  185.             sprintf(text, "%s: connection reset", msg);
  186.             break;
  187.         case EISCONN:
  188.             sprintf(text, "%s: already connected", msg);
  189.             break;
  190.         case ENOTCONN:
  191.             sprintf(text, "%s: not connected", msg);
  192.             break;
  193.         case ESHUTDOWN:
  194.             sprintf(text, "%s: connection shutdown", msg);
  195.             break;
  196.         case ETIMEDOUT:
  197.             sprintf(text, "%s: connection timedout", msg);
  198.             break;
  199.         case ECONNREFUSED:
  200.             sprintf(text, "%s: connection refused", msg);
  201.             break;
  202.         case EHOSTDOWN:
  203.             sprintf(text, "%s: no route to host", msg);
  204.             break;
  205.         default:
  206.             sprintf(text, "%s: socket error %d", msg, err_code);
  207.             break;
  208.     }
  209.  
  210.     error(text);
  211. }
  212.  
  213. void ReceivedFrame(FILE *fp, char *fileName)
  214. {
  215.     int bytes;
  216.     int type;
  217.     int length;
  218.  
  219.     if ((bytes = read(s, buffer, 512)) < 0)
  220.         socket_error("read failed", errno);
  221.  
  222.     length = buffer[0] + ((buffer[1] << 3) & 0xFF00);
  223.     type   = buffer[1] & 0x1F;
  224.  
  225.     switch (state)
  226.     {
  227.         case LOGGING_IN:
  228.             if (type != LOGIN_RESP)
  229.             {
  230.                 sprintf(msg, "Expected LOGIN_RESP got %d", type);
  231.                 error(msg);
  232.             }
  233.             
  234.             update_status("Status: Logged in");
  235.  
  236.             /* request an upload */
  237.             sprintf(msg, "Status: Requesting upload: file:%lx length:%d",
  238.                     fileId, fileLength);
  239.             update_status(msg);
  240.  
  241.             buffer[0] = sizeof(UPLOAD_REQUEST);
  242.             buffer[1] = UPLOAD_CMD;
  243.             
  244.             ul_request         = (UPLOAD_REQUEST *)&buffer[2];
  245.             ul_request->file   = fileId;
  246.             ul_request->length = fileLength;
  247.     
  248.             if (writen(s, (char *)buffer, sizeof(UPLOAD_REQUEST) + 2) != (sizeof(UPLOAD_REQUEST) + 2))
  249.                 socket_error("write failed", errno);
  250.  
  251.             state = REQUESTING_UPLOAD;
  252.             break;
  253.  
  254.         case REQUESTING_UPLOAD:
  255.             switch (type)
  256.             {
  257.                 case UL_GO_RESP:
  258.                     break;
  259.                 case UL_ERROR_RESP:
  260.                     ftl0_error("Received UL_ERROR_RESP", buffer[2]);
  261.                 default:
  262.                     sprintf(msg, "Received unexpected GO_RESP: %d", type);
  263.                     error(msg);
  264.             }
  265.  
  266.             ul_response = (UPLOAD_RESPONSE *)&buffer[2];
  267.             offset       = ul_response->offset;
  268.             uploadFileId = ul_response->file;
  269.  
  270.             sprintf(msg, "Status: Received GO_RESP: file:%lx offset:%ld",
  271.                 uploadFileId, offset);
  272.             update_status(msg);
  273.  
  274.             /* update the file id in the header */
  275.             /* incase it does not all make it */
  276.             fseek(fp, 5L, SEEK_SET);
  277.             fwrite((char *)&uploadFileId, 1, 4, fp);
  278.  
  279.             /* now seek to the start of the data and start uploading */
  280.             fseek(fp, offset, SEEK_SET);
  281.             state = UPLOADING;
  282.             break;
  283.  
  284.         case UPLOADING:
  285.             switch (type)
  286.             {
  287.                 case UL_NAK_RESP:
  288.                     /* send a data end packet */
  289.                     buffer[0] = 0;
  290.                     buffer[1] = DATA_END;
  291.                     if (writen(s, buffer, 2) != 2)
  292.                         socket_error("write failed", errno);
  293.                     ftl0_error("Received UL_NAK_RESP", buffer[2]);
  294.                 default:
  295.                     sprintf(msg, "Received unexpected response: %d", type);
  296.                     error(msg);
  297.             }
  298.  
  299.         case SENT_END_DATA:
  300.             switch (type)
  301.             {
  302.                 case UL_ACK_RESP:
  303.                     break;
  304.                 case UL_NAK_RESP:
  305.                     ftl0_error("Received UL_NAK_RESP", buffer[2]);
  306.                 default:
  307.                     sprintf(msg, "Received unexpected response: %d", type);
  308.                     error(msg);
  309.             }
  310.  
  311.             sprintf(msg, "Status: File %s uploaded as message %lx", fileName, uploadFileId);
  312.             update_status(msg);
  313.  
  314.             unlink(fileName);
  315.  
  316.             close(s);
  317.             sleep(1);
  318.  
  319.             exit(0);
  320.     }
  321. }
  322.  
  323. void SendFrame(FILE *fp, char *fileName)
  324. {
  325.     int bytes;
  326.  
  327.     if ((bytes = fread(buffer + 2, 1, maxFrame, fp)) > 0)
  328.     {
  329.         buffer[0] = bytes;
  330.         buffer[1] = DATA;
  331.  
  332.         /* always send fileId of 0 in header */
  333.         if (offset == 0L)
  334.         {
  335.             buffer[7]  = 0;
  336.             buffer[8]  = 0;
  337.             buffer[9]  = 0;
  338.             buffer[10] = 0;
  339.         }
  340.  
  341.         if (writen(s, buffer, bytes + 2) != (bytes + 2))
  342.             socket_error("write failed", errno);
  343.  
  344.         offset += bytes;
  345.         return;
  346.     }
  347.  
  348.     if (bytes < 0) socket_error("read failed", errno);
  349.  
  350.     fclose(fp);
  351.  
  352.     /* send a data end packet */
  353.     buffer[0] = 0;
  354.     buffer[1] = DATA_END;
  355.  
  356.     if (writen(s, buffer, 2) != 2)
  357.         socket_error("write failed", errno);
  358.  
  359.     state = SENT_END_DATA;
  360. }
  361.  
  362. void upload(char *fileName)
  363. {
  364.     HEADER *pHeader;
  365.     int opt;
  366.     int addr_len;
  367.     struct full_sockaddr_ax25 addr;
  368.     int bytes;
  369.     fd_set rx, tx;
  370.  
  371.     sprintf(msg, "Status: Uploading: %s", fileName);
  372.     update_status(msg);
  373.  
  374.     if ((fp = fopen(fileName, "r+")) == NULL)
  375.         error("File open failed");
  376.  
  377.     /* get the file length */
  378.     fseek(fp, 0L, SEEK_END);
  379.     fileLength = ftell(fp);
  380.  
  381.     /* extracting the header */
  382.     fseek(fp, 0L, SEEK_SET);
  383.     bytes = fread(buffer, 1, 1024, fp);
  384.  
  385.     fseek(fp, 0L, SEEK_SET);
  386.     pHeader = ExtractHeader(buffer, bytes, &bytes);
  387.     fileId = pHeader->fileId;
  388.     XtFree((char *)pHeader);
  389.  
  390.     if ((s = socket(AF_AX25, SOCK_SEQPACKET, PF_AX25)) < 0)
  391.         socket_error("Socket open failed", errno);
  392.  
  393.     opt = 1;
  394.  
  395.     if (setsockopt(s, SOL_AX25, AX25_WINDOW, &opt, sizeof(opt)) == -1)
  396.         socket_error("setsockopt (AX25_WINDOW) failed", errno);
  397.  
  398.     if (setsockopt(s, SOL_AX25, AX25_T1, &T1, sizeof(opt)) == -1)
  399.         socket_error("setsockopt (AX25_T1) failed", errno);
  400.  
  401. #ifdef DEBUG
  402.     opt = 1;
  403.  
  404.     if (setsockopt(s, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt)) == -1)
  405.         socket_error("setsockopt (SO_DEBUG) failed", errno);
  406. #endif
  407.  
  408.     addr_len = convert_call(myCall, &addr);
  409.  
  410.     if (bind(s, (struct sockaddr *)&addr, addr_len) == -1)
  411.         socket_error("bind failed", errno);
  412.  
  413.     addr_len = convert_call(satellite, &addr);
  414.  
  415.     update_status("Status: Connecting...");
  416.  
  417.     if (connect(s, (struct sockaddr *)&addr, addr_len) != 0)
  418.         socket_error("connect failed", errno);
  419.  
  420.     update_status("Status: Connected");
  421.  
  422.     /* setup state */
  423.     state = LOGGING_IN;
  424.  
  425.     for (;;)
  426.     {
  427.         FD_ZERO(&rx);
  428.         FD_ZERO(&tx);
  429.  
  430.         FD_SET(s, &rx);
  431.  
  432.         if (state == UPLOADING)
  433.         {
  434.             FD_SET(s, &tx);    
  435.             select(s + 1, &rx, &tx, NULL, NULL);
  436.         }
  437.         else
  438.         {
  439.             select(s + 1, &rx, NULL, NULL, NULL);
  440.         }
  441.                 
  442.         if (FD_ISSET(s, &rx)) ReceivedFrame(fp, fileName);
  443.         
  444.         if (FD_ISSET(s, &tx)) SendFrame(fp, fileName);
  445.     }
  446. }
  447.  
  448. /*
  449.  *    Library routine for callsign conversion.
  450.  *
  451.  */
  452.  
  453. void convert_call_entry(char *name,unsigned char *buf)
  454. {
  455.     int ct = 0;
  456.     int ssid = 0;
  457.     char *p = name;
  458.  
  459.     while (ct < 6)
  460.     {
  461.         if (*p == '-' || *p == '\0') break;
  462.  
  463.         if (islower(*p)) *p = toupper(*p);
  464.  
  465.         if (!isalnum(*p))
  466.         {
  467.             sprintf(msg, "Invalid symbol in callsign - %c\n", *p);
  468.             error(msg);
  469.         }
  470.         
  471.         buf[ct] = (*p << 1);
  472.         p++;
  473.         ct++;
  474.     }
  475.  
  476.     while (ct < 6)
  477.     {
  478.         buf[ct] = ' ' << 1;
  479.         ct++;
  480.     }
  481.  
  482.     if (*p == '-')
  483.     {
  484.         p++;
  485.  
  486.         if (sscanf(p, "%d", &ssid) != 1 || ssid < 0 || ssid > 15)
  487.         {
  488.             sprintf(msg, "Invalid SSID - %s - %s\n", name, p);
  489.             error(msg);
  490.         }
  491.     }
  492.  
  493.     buf[6] = ((ssid + '0') << 1) & 0x1E;
  494. }
  495.  
  496. int convert_call(char *call, struct full_sockaddr_ax25 *sax)
  497. {
  498.  
  499.     int len = 0;
  500.     unsigned char *bp, *np;
  501.     char *addrp;
  502.     int n = 0;
  503.     unsigned char *tmp = strdup(call);
  504.     
  505.     if (tmp == NULL) return -1;
  506.         
  507.     bp = tmp;
  508.     
  509.     addrp = sax->fsa_ax25.sax25_call.ax25_call;
  510.  
  511.     do
  512.     {
  513.         /* Fetch one callsign token */
  514.         while (*bp && isspace(*bp)) bp++;
  515.         np = bp;
  516.         while (*np && !isspace(*np)) np++;
  517.         if (*np) *np++ = 0;
  518.     
  519.         /* Check for the optional 'via' syntax */
  520.         if (n == 1 && (strcasecmp(bp, "V") == 0 || strcasecmp(bp, "VIA") == 0))
  521.         {
  522.             bp = np;
  523.             continue;
  524.         }
  525.         
  526.         /* Process the token */
  527.         convert_call_entry(bp, addrp);
  528.             
  529.         /* Move along */
  530.         bp = np;
  531.         n++;
  532.  
  533.         if (n == 1)
  534.         {
  535.             addrp = sax->fsa_digipeater[0].ax25_call;    /* First digipeater address */
  536.             len  += sizeof(struct sockaddr_ax25);
  537.         }
  538.         else
  539.         {
  540.             addrp += sizeof(ax25_address);
  541.             len   += sizeof(ax25_address);
  542.         }
  543.     }
  544.     while (n < AX25_MAX_DIGIS && *bp);
  545.  
  546.     free(tmp);
  547.  
  548.     /* Tidy up */
  549.     sax->fsa_ax25.sax25_ndigis = n - 1;
  550.     sax->fsa_ax25.sax25_family = AF_AX25;    
  551.  
  552.     return len;
  553. }
  554.  
  555.